﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using NumericalData.Interpolation.Data;
using WPFSolution.CommonOperations;
using WPFSolution.UserControls;
using MessageBox = System.Windows.MessageBox;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using TextBox = System.Windows.Controls.TextBox;
using UserControl = System.Windows.Controls.UserControl;

namespace WPFSolution.UserControls
{
    /// <summary>
    /// Interaction logic for InterpolationFunctionEditor.xaml
    /// </summary>
    public partial class InterpolationFunctionEditor : UserControl
    {
        public delegate void FunctionDataCreatedDelegate(ExpressionContainer container);

        public event FunctionDataCreatedDelegate FunctionDataCreated;

        public InterpolationFunctionEditor()
        {
            InitializeComponent();
            CalculateIntervalWidth();
            funcEvaluator.HistoryUpdated += SetFieldsByFound;
            funcEvaluator.ExpressionEvaluated += GotExpressionContainer;
        }

        #region FunctionEvaluator Handlers
        #endregion
        void GotExpressionContainer(ExpressionContainer container)
        {
            //MessageBox.Show("GotExpressionContainer");
            if (FunctionDataCreated != null)
                FunctionDataCreated(container);
        }
        private void SetFieldsByFound(ExpressionContainer exp)
        {
            fromTextBox.Text = exp.IntervalStart.ToString();
            toTextBox.Text = exp.IntervalStop.ToString();
            pointsNumberSlider.Value = exp.Grid.Count;
            CalculateIntervalWidth();
        }

        #region Fields Methods
        public double GetIntStart()
        {
            return GUIManipulator.GetDoubleValue(fromTextBox, -1, 999999, -999999);
        }

        public double GetIntStop()
        {
            return GUIManipulator.GetDoubleValue(toTextBox, -1, 999999, -999999);
        }

        public int GetNumberOfPoints()
        {
            return GUIManipulator.GetIntValue(pointsNumberTextBox, 101, 10001, 101);
        }

        public int GetMethodOrder()
        {
            return GUIManipulator.GetIntValue(methodOrderTextBox, 10, 20, 3);
        }

        private void CalculateIntervalWidth()
        {
            var from = GetIntStart();
            var to = GetIntStop();
            var numberOfPoints = GetNumberOfPoints();
            intervalWidthTextBox.Text = ((to - from) / numberOfPoints).ToString();
        }

        private void NormalizeIntervalEnds()
        {
            var from = GetIntStart();
            var to = GetIntStop();
            if (to < from)
            {
                fromTextBox.Text = to.ToString();
            }
        }
        #endregion

        private bool TryGetGridFromFile()
        {
            using (var fileDialog = new OpenFileDialog())
            {
                fileDialog.AutoUpgradeEnabled = true;
                fileDialog.CheckFileExists = true;
                fileDialog.CheckPathExists = true;
                fileDialog.Title = "Load Grid From File";
                fileDialog.DefaultExt = ".txt, .csv";
                fileDialog.Filter = "Text files|*.csv";// "|(*.csv)";
                DialogResult result = fileDialog.ShowDialog();
                if (result == DialogResult.OK)
                {
                    try
                    {
                        var grid = EquidistantPointsGrid.ExecuteFromFile(fileDialog.FileName);
                        var fileShortName = fileDialog.SafeFileName;
                        var order = GetMethodOrder();
                        if(!funcEvaluator.TryLoadExpressionFromGrid(grid, fileShortName, order))
                            throw new Exception("Can't load grid from file!");
                        SetFieldsByFound(funcEvaluator.CurrentExpression);
                        return true;
                    }
                    catch (Exception exc)
                    {
                        MessageBox.Show("Operation failed:\n" + exc.Message, "An error occurred!",
                            MessageBoxButton.OK, MessageBoxImage.Error);
                        return false;
                    }
                }
                return false;
            }
        }

        #region Fields Events

        private void IntervalPointTextChanged(object sender, RoutedEventArgs e)
        {
            var textBox = (TextBox)sender;
            textBox.Text = GUIManipulator.GetDoubleValue(textBox, -1, 999999, -999999).ToString();
            NormalizeIntervalEnds();
            CalculateIntervalWidth();
        }

        private void IntervalPointTextBoxMouseLeave(object sender, MouseEventArgs e)
        {
            IntervalPointTextChanged(sender, e);
        }

        private void PointsNumberSliderPreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            CalculateIntervalWidth();
        }

        private void methodOrderTextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            methodOrderTextBox.Text = GetMethodOrder().ToString();
        }

        private void methodOrderTextBox_MouseLeave(object sender, MouseEventArgs e)
        {
            methodOrderTextBox.Text = GetMethodOrder().ToString();
        }
        #endregion

        private void loadFromFileButton_Click(object sender, RoutedEventArgs e)
        {
            TryGetGridFromFile();
        }



    }
}
